package main

import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"os"

	"../kp/prowatcher/pb"
	"golang.org/x/net/context"
)

type pwatcher struct {
	tk         pb.Token
	cli        pb.WatcherServiceClient
	clks       map[string]*CmdLink
	defineFile string
}

type CmdLink struct {
	Cmdlink []string          `json:"cmdlink"`
	Judge   map[string]string `json:"judge"`
	CmdArgs map[string]string `json:"cmdargs"`
}

func Newpwatcher(tk *pb.Token, cli *pb.WatcherServiceClient, fn string) (pw *pwatcher, err error) {
	if tk == nil {
		return nil, errors.New("token is nil")
	}
	if cli == nil {
		return nil, errors.New("client connection is nil")
	}
	p := &pwatcher{
		tk:  *tk,
		cli: *cli,
	}
	f, err := os.Stat(fn)
	if err != nil || f.IsDir() {
		log.Errorf("config file can't open: %v", err)
		return nil, fmt.Errorf("can't open: %v", err)
	}
	b, err := ioutil.ReadFile(fn)
	if err != nil {
		log.Errorf("config file can't open: %v", err)
		return nil, err
	}
	err = json.Unmarshal(b, &p.clks)
	if err != nil {
		return nil, err
	}
	p.defineFile = fn
	return p, nil
}

//type wtool interface {
//	Run(string, string) ([]string, error)
//	Query(string, bool) (*pb.Status, error)
//	List() ([]string, error)
//	Show(string, string) (map[string]string, error)
//	Watch(string, string, bool) error
//}

func (pw *pwatcher) Run(procName, cmdName string, cmdArgs []string) ([]string, error) {
	x, err := pw.cli.Run(context.Background(), &pb.RunRequest{Token: &pw.tk, ProcName: procName, CommandName: cmdName, CommandArgs: cmdArgs})
	var s []string
	if err != nil {
		return nil, err
	}
	for {
		response, err := x.Recv()
		if err != nil {
			return nil, err
		}
		if !response.GetSuccess() {
			for _, l := range response.Line {
				s = append(s, l)
			}
		} else {
			log.Infof("proc %s run [%s] success!!!", procName, cmdName)
			return s, nil
		}
	}
}

func (pw *pwatcher) Query(procName string, refresh bool) (*pb.Status, error) {
	x, err := pw.cli.Query(context.Background(), &pb.QueryWatcherRequest{Token: &pw.tk, ProcName: procName, Refresh: refresh})
	if err != nil {
		return nil, err
	}
	sta := x.GetStatus()
	xerr := x.GetErr()
	if xerr != "" {
		return nil, fmt.Errorf("query err is %v", xerr)
	}
	if sta != nil {
		log.Infof("proc %s==> %s", procName, sta.String())
	}
	return sta, nil
}

/*func (pw *pwatcher) List() (pro []string, err error) {
	x, xerr := pw.cli.List(context.Background(), &pb.ListRequest{Token: &pw.tk})
	if xerr != nil {
		return nil, xerr
	}
	pro = x.GetProcName()
	perr := x.GetErr()
	if perr != "" {
		return nil, errors.New(perr)
	}
	if pro != nil {
		log.Infof("pro==> %s", x.String())
	} else {
		return nil, errors.New("pro is nil")
	}
	return pro, nil
}*/

func (pw *pwatcher) List() error {
	x, xerr := pw.cli.List(context.Background(), &pb.ListRequest{Token: &pw.tk})
	if xerr != nil {
		return xerr
	}
	pro := x.GetProcName()
	perr := x.GetErr()
	if perr != "" {
		return fmt.Errorf("list err is %v", perr)
	}
	if pro != nil {
		log.Infof("pro==> %s", x.String())
	} else {
		return errors.New("pro is nil")
	}
	return nil
}

/*func (pw *pwatcher) Show(procName, cmdName string) (cmd map[string]string, err error) {
	x, xerr := pw.cli.Show(context.Background(), &pb.ShowRequest{Token: &pw.tk, ProcName: procName, CommandName: cmdName})
	if xerr != nil {
		return nil, xerr
	}
	cmd = x.GetCommands()
	cerr := x.GetErr()
	if cerr != "" {
		return nil, errors.New(cerr)
	}
	if cmd != nil {
		log.Infof("Proc %s cmd==> %s", procName, x.String())
	} else {
		return nil, errors.New("cmd is nil")
	}
	return cmd, nil
}*/

func (pw *pwatcher) Show(procName, cmdName string) error {
	x, xerr := pw.cli.Show(context.Background(), &pb.ShowRequest{Token: &pw.tk, ProcName: procName, CommandName: cmdName})
	if xerr != nil {
		return xerr
	}
	cmd := x.GetCommands()
	cerr := x.GetErr()
	if cerr != "" {
		return fmt.Errorf("show err is %v", cerr)
	}
	if cmd != nil {
		log.Infof("Proc %s cmd==> %s", procName, x.String())
	} else {
		return errors.New("cmd is nil")
	}
	return nil
}

//func (pw *pwatcher) Watch(procName, cmdName string, refresh bool) error {
//	for {
//		x, err := pw.cli.Query(context.Background(), &pb.QueryWatcherRequest{Token: &pw.tk, ProcName: procName, Refresh: refresh})
//		if err != nil {
//			log.Error(err)
//			return err
//		}
//		sta := x.GetStatus()
//		xerr := x.GetErr()
//		if xerr != "" {
//			log.Errorf("query err is %v", xerr)
//			return errors.New(xerr)
//		}
//		if sta != nil {
//			log.Infof("proc %s==> %s", procName, x.String())
//			return nil
//		} else {
//			x, err := pw.cli.Run(context.Background(), &pb.RunRequest{Token: &pw.tk, ProcName: procName, CommandName: cmdName})
//			if err != nil {
//				log.Error(err)
//				return err
//			}
//			for {
//				response, err := x.Recv()
//				if err == io.EOF {
//					break
//				}
//				if err != nil {
//					log.Errorf("err is %v", err)
//					break
//				}
//				if !response.GetSuccess() {
//					for _, l := range response.Line {
//						log.Infof("%s", l)
//					}
//				} else {
//					log.Info("success!!!")
//				}
//			}
//		}
//	}
//}
